home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
util
/
arc
/
PPCxDMSWOS.lha
/
source.lha
/
src
/
pfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-17
|
12KB
|
457 lines
/*
* xDMS v1.0 - Portable DMS archive unpacker - Public Domain
* Written by Andre R. de la Rocha <adlroc@usa.net>
*
* Handles the processing of a single DMS archive
*
*/
#define HEADLEN 56
#define THLEN 20
#define TRACK_BUFFER_LEN 32768
#define TEMP_BUFFER_LEN 32768
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "cdata.h"
#include "u_rle.h"
#include "u_quick.h"
#include "u_medium.h"
#include "u_deep.h"
#include "u_heavy.h"
#include "crc_csum.h"
#include "pfile.h"
static USHORT Process_Track(FILE *, FILE *, UCHAR *, UCHAR *, USHORT, USHORT, USHORT);
static USHORT Unpack_Track(UCHAR *, UCHAR *, USHORT, USHORT, UCHAR, UCHAR);
static void printbandiz(UCHAR *, USHORT);
static void dms_decrypt(UCHAR *, USHORT);
static char modes[7][7]={"NOCOMP","SIMPLE","QUICK ","MEDIUM","DEEP ","HEAVY1","HEAVY2"};
static USHORT PWDCRC;
UCHAR *text;
USHORT Process_File(char *iname, char *oname, USHORT cmd, USHORT opt, USHORT PCRC, USHORT pwd){
FILE *fi, *fo=NULL;
USHORT from, to, geninfo, c_version, cmode, hcrc, disktype, pv, ret;
ULONG pkfsize, unpkfsize;
UCHAR *b1, *b2;
time_t date;
b1 = (UCHAR *)calloc(TRACK_BUFFER_LEN,1);
if (b1==NULL) return ERR_NOMEMORY;
b2 = (UCHAR *)calloc(TRACK_BUFFER_LEN,1);
if (b2==NULL) {
free(b1);
return ERR_NOMEMORY;
}
text = (UCHAR *)calloc(TEMP_BUFFER_LEN,1);
if (text==NULL) {
free(b1);
free(b2);
return ERR_NOMEMORY;
}
/* if iname is NULL, input is stdin; if oname is NULL, output is stdout */
if (iname){
fi = fopen(iname,"rb");
if (fi==NULL) {
free(b1);
free(b2);
free(text);
return ERR_CANTOPENIN;
}
} else {
fi = stdin;
}
if (fread(b1,1,HEADLEN,fi) != HEADLEN) {
if (iname) fclose(fi);
free(b1);
free(b2);
free(text);
return ERR_SREAD;
}
if ( (b1[0] != 'D') || (b1[1] != 'M') || (b1[2] != 'S') || (b1[3] != '!') ) {
/* Check the first 4 bytes of file to see if it is "DMS!" */
if (iname) fclose(fi);
free(b1);
free(b2);
free(text);
return ERR_NOTDMS;
}
hcrc = (USHORT)((b1[HEADLEN-2]<<8) | b1[HEADLEN-1]);
/* Header CRC */
if (hcrc != CreateCRC(b1+4,(ULONG)(HEADLEN-6))) {
if (iname) fclose(fi);
free(b1);
free(b2);
free(text);
return ERR_HCRC;
}
geninfo = (USHORT) ((b1[10]<<8) | b1[11]); /* General info about archive */
date = (time_t) ((((ULONG)b1[12])<<24) | (((ULONG)b1[13])<<16) | (((ULONG)b1[14])<<8) | (ULONG)b1[15]); /* date in standard UNIX/ANSI format */
from = (USHORT) ((b1[16]<<8) | b1[17]); /* Lowest track in archive. May be incorrect if archive is "appended" */
to = (USHORT) ((b1[18]<<8) | b1[19]); /* Highest track in archive. May be incorrect if archive is "appended" */
pkfsize = (ULONG) ((((ULONG)b1[21])<<16) | (((ULONG)b1[22])<<8) | (ULONG)b1[23]); /* Length of total packed data as in archive */
unpkfsize = (ULONG) ((((ULONG)b1[25])<<16) | (((ULONG)b1[26])<<8) | (ULONG)b1[27]); /* Length of unpacked data. Usually 901120 bytes */
c_version = (USHORT) ((b1[46]<<8) | b1[47]); /* version of DMS used to generate it */
disktype = (USHORT) ((b1[50]<<8) | b1[51]); /* Type of compressed disk */
cmode = (USHORT) ((b1[52]<<8) | b1[53]); /* Compression mode mostly used in this archive */
PWDCRC = PCRC;
if ( (cmd == CMD_VIEW) || (cmd == CMD_VIEWFULL) ) {
if (iname)
printf("\n File : %s\n",iname);
else
printf("\n Data from stdin\n");
pv = (USHORT)(c_version/100);
printf(" Created with DMS version %d.%02d ",pv,c_version-pv*100);
if (geninfo & 0x80)
printf("Registered\n");
else
printf("Evaluation\n");
printf(" Creation date : %s",ctime(&date));
printf(" Lowest track in archive : %d\n",from);
printf(" Highest track in archive : %d\n",to);
printf(" Packed data size : %lu\n",pkfsize);
printf(" Unpacked data size : %lu\n",unpkfsize);
printf(" Disk type of archive : ");
/* The original DMS from SDS software (DMS up to 1.11) used other values */
/* in disk type to indicate formats as MS-DOS, AMax and Mac, but it was */
/* not suported for compression. It was for future expansion and was never */
/* used. The newer versions of DMS made by ParCon Software changed it to */
/* add support for new Amiga disk types. */
switch (disktype) {
case 0:
case 1:
/* Can also be a non-dos disk */
printf("AmigaOS 1.0 OFS\n");
break;
case 2:
printf("AmigaOS 2.0 FFS\n");
break;
case 3:
printf("AmigaOS 3.0 OFS / International\n");
break;
case 4:
printf("AmigaOS 3.0 FFS / International\n");
break;
case 5:
printf("AmigaOS 3.0 OFS / Dir Cache\n");
break;
case 6:
printf("AmigaOS 3.0 FFS / Dir Cache\n");
break;
case 7:
printf("FMS Amiga System File\n");
break;
default:
printf("Unknown\n");
}
printf(" Compression mode used : ");
if (cmode>6)
printf("Unknown !\n");
else
printf("%s\n",modes[cmode]);
printf(" General info : ");
if ((geninfo==0)||(geninfo==0x80)) printf("None");
if (geninfo & 1) printf("NoZero ");
if (geninfo & 2) printf("Encrypted ");
if (geninfo & 4) printf("Appends ");
if (geninfo & 8) printf("Banner ");
if (geninfo & 16) printf("HD ");
if (geninfo & 32) printf("MS-DOS ");
if (geninfo & 64) printf("DMS_DEV_Fixed ");
if (geninfo & 256) printf("FILEID.DIZ");
printf("\n");
printf(" Info Header CRC : %04X\n\n",hcrc);
}
if (disktype == 7) {
/* It's not a DMS compressed disk image, but a FMS archive */
if (iname) fclose(fi);
free(b1);
free(b2);
free(text);
return ERR_FMS;
}
if (cmd == CMD_VIEWFULL) {
printf(" Track Plength Ulength Cmode USUM HCRC DCRC Cflag\n");
printf(" ------ ------- ------- ------ ---- ---- ---- -----\n");
}
if (((cmd==CMD_UNPACK) || (cmd==CMD_SHOWBANNER)) && (geninfo & 2) && (pwd==0))
return ERR_NOPASSWD;
if (cmd == CMD_UNPACK) {
if (oname){
fo = fopen(oname,"wb");
if (fo==NULL) {
if (iname) fclose(fi);
free(b1);
free(b2);
free(text);
return ERR_CANTOPENOUT;
}
} else {
fo = stdout;
}
}
ret=NO_PROBLEM;
Init_QUICK();
Init_MEDIUM();
Init_DEEP();
Init_HEAVY();
if (cmd != CMD_VIEW) {
if (cmd == CMD_SHOWBANNER) /* Banner is in the first track */
ret = Process_Track(fi,NULL,b1,b2,cmd,opt,(geninfo & 2)?pwd:0);
else {
while ( (ret=Process_Track(fi,fo,b1,b2,cmd,opt,(geninfo & 2)?pwd:0)) == NO_PROBLEM ) ;
if ((cmd == CMD_UNPACK) && (opt == OPT_VERBOSE)) fprintf(stderr,"\n");
}
}
if ((cmd == CMD_VIEWFULL) || (cmd == CMD_SHOWDIZ) || (cmd == CMD_SHOWBANNER)) printf("\n");
if (ret == FILE_END) ret = NO_PROBLEM;
/* Used to give an error message, but I have seen some DMS */
/* files with texts or zeros at the end of the valid data */
/* So, when we find something that is not a track header, */
/* we suppose that the valid data is over. And say it's ok. */
if (ret == ERR_NOTTRACK) ret = NO_PROBLEM;
if (iname) fclose(fi);
if ((cmd == CMD_UNPACK) && oname) fclose(fo);
free(b1);
free(b2);
free(text);
return ret;
}
static USHORT Process_Track(FILE *fi, FILE *fo, UCHAR *b1, UCHAR *b2, USHORT cmd, USHORT opt, USHORT pwd){
USHORT hcrc, dcrc, usum, number, pklen1, pklen2, unpklen, l, r;
UCHAR cmode, flags;
l = (USHORT)fread(b1,1,THLEN,fi);
if (l != THLEN) {
if (l == 0)
return FILE_END;
else
return ERR_SREAD;
}
/* "TR" identifies a Track Header */
if ((b1[0] != 'T')||(b1[1] != 'R')) return ERR_NOTTRACK;
/* Track Header CRC */
hcrc = (USHORT)((b1[THLEN-2] << 8) | b1[THLEN-1]);
if (CreateCRC(b1,(ULONG)(THLEN-2)) != hcrc) return ERR_THCRC;
number = (USHORT)((b1[2] << 8) | b1[3]); /* Number of track */
pklen1 = (USHORT)((b1[6] << 8) | b1[7]); /* Length of packed track data as in archive */
pklen2 = (USHORT)((b1[8] << 8) | b1[9]); /* Length of data after first unpacking */
unpklen = (USHORT)((b1[10] << 8) | b1[11]); /* Length of data after subsequent rle unpacking */
flags = b1[12]; /* control flags */
cmode = b1[13]; /* compression mode used */
usum = (USHORT)((b1[14] << 8) | b1[15]); /* Track Data CheckSum AFTER unpacking *